#!/usr/bin/env python3
"""
存储策略调整器
根据磁盘空间动态调整存储策略
"""

import os
import time
import threading
from typing import Dict, Any, Optional, Callable
from dataclasses import dataclass
from .disk_monitor import DiskMonitor, StorageLevel, StorageRecommendation

@dataclass
class StorageConfig:
    """存储配置"""
    buffer_size: int = 1000          # 缓冲区大小
    page_size: int = 4096           # 页面大小
    max_pages: int = 1000           # 最大页面数
    cleanup_threshold: int = 200    # 清理阈值
    compression_enabled: bool = False  # 是否启用压缩
    auto_cleanup: bool = True       # 是否自动清理

class StorageAdjuster:
    """存储策略调整器"""
    
    def __init__(self, data_directory: str = "data"):
        self.data_directory = data_directory
        self.disk_monitor = DiskMonitor(data_directory)
        self.current_config = StorageConfig()
        self.base_config = StorageConfig()  # 基础配置
        self.adjustment_callbacks: Dict[str, Callable] = {}
        self.monitoring_thread: Optional[threading.Thread] = None
        self.monitoring_active = False
        self.last_adjustment_time = 0
        self.adjustment_cooldown = 60  # 调整冷却时间(秒)
        
        # 存储级别对应的配置调整
        self.level_configs = {
            StorageLevel.CRITICAL: {
                'buffer_size_factor': 0.3,
                'max_pages_factor': 0.5,
                'cleanup_threshold_factor': 0.5,
                'compression_enabled': True,
                'auto_cleanup': True
            },
            StorageLevel.LOW: {
                'buffer_size_factor': 0.5,
                'max_pages_factor': 0.7,
                'cleanup_threshold_factor': 0.7,
                'compression_enabled': True,
                'auto_cleanup': True
            },
            StorageLevel.NORMAL: {
                'buffer_size_factor': 1.0,
                'max_pages_factor': 1.0,
                'cleanup_threshold_factor': 1.0,
                'compression_enabled': False,
                'auto_cleanup': True
            },
            StorageLevel.HIGH: {
                'buffer_size_factor': 1.2,
                'max_pages_factor': 1.2,
                'cleanup_threshold_factor': 1.5,
                'compression_enabled': False,
                'auto_cleanup': False
            },
            StorageLevel.EXCESS: {
                'buffer_size_factor': 1.5,
                'max_pages_factor': 1.5,
                'cleanup_threshold_factor': 2.0,
                'compression_enabled': False,
                'auto_cleanup': False
            }
        }
    
    def register_callback(self, event: str, callback: Callable):
        """注册调整回调函数"""
        self.adjustment_callbacks[event] = callback
    
    def _trigger_callback(self, event: str, data: Any = None):
        """触发回调函数"""
        if event in self.adjustment_callbacks:
            try:
                self.adjustment_callbacks[event](data)
            except Exception as e:
                print(f"回调函数执行失败: {e}")
    
    def get_current_config(self) -> StorageConfig:
        """获取当前配置"""
        return self.current_config
    
    def update_base_config(self, config: StorageConfig):
        """更新基础配置"""
        self.base_config = config
        self.current_config = config
    
    def adjust_storage_strategy(self, force: bool = False) -> Dict[str, Any]:
        """调整存储策略"""
        current_time = time.time()
        
        # 检查冷却时间
        if not force and (current_time - self.last_adjustment_time) < self.adjustment_cooldown:
            return {'adjusted': False, 'reason': '冷却时间未到'}
        
        # 获取磁盘信息
        disk_info = self.disk_monitor.get_disk_info()
        recommendation = self.disk_monitor.get_storage_recommendation(disk_info)
        
        # 获取对应级别的配置
        level_config = self.level_configs.get(disk_info.level, self.level_configs[StorageLevel.NORMAL])
        
        # 计算新的配置
        new_config = StorageConfig(
            buffer_size=int(self.base_config.buffer_size * level_config['buffer_size_factor']),
            page_size=self.base_config.page_size,  # 页面大小通常不变
            max_pages=int(self.base_config.max_pages * level_config['max_pages_factor']),
            cleanup_threshold=int(self.base_config.cleanup_threshold * level_config['cleanup_threshold_factor']),
            compression_enabled=level_config['compression_enabled'],
            auto_cleanup=level_config['auto_cleanup']
        )
        
        # 检查是否需要调整
        config_changed = (
            new_config.buffer_size != self.current_config.buffer_size or
            new_config.max_pages != self.current_config.max_pages or
            new_config.cleanup_threshold != self.current_config.cleanup_threshold or
            new_config.compression_enabled != self.current_config.compression_enabled or
            new_config.auto_cleanup != self.current_config.auto_cleanup
        )
        
        if not config_changed and not force:
            return {'adjusted': False, 'reason': '配置无需调整'}
        
        # 应用新配置
        old_config = self.current_config
        self.current_config = new_config
        self.last_adjustment_time = current_time
        
        # 触发调整事件
        adjustment_data = {
            'old_config': old_config,
            'new_config': new_config,
            'disk_info': disk_info,
            'recommendation': recommendation
        }
        
        self._trigger_callback('storage_adjusted', adjustment_data)
        
        # 如果启用了自动清理且空间不足，执行清理
        if new_config.auto_cleanup and disk_info.level in [StorageLevel.CRITICAL, StorageLevel.LOW]:
            self._perform_auto_cleanup()
        
        return {
            'adjusted': True,
            'old_config': old_config,
            'new_config': new_config,
            'disk_info': disk_info,
            'recommendation': recommendation
        }
    
    def _perform_auto_cleanup(self):
        """执行自动清理"""
        print("执行自动清理...")
        
        # 清理临时文件
        cleaned_files = self.disk_monitor.cleanup_temp_files()
        print(f"清理了 {cleaned_files} 个临时文件")
        
        # 触发清理事件
        self._trigger_callback('auto_cleanup', {'cleaned_files': cleaned_files})
    
    def start_monitoring(self, interval: int = 30):
        """开始监控"""
        if self.monitoring_active:
            return
        
        self.monitoring_active = True
        self.monitoring_thread = threading.Thread(
            target=self._monitoring_loop,
            args=(interval,),
            daemon=True
        )
        self.monitoring_thread.start()
        print(f"存储监控已启动，间隔: {interval}秒")
    
    def stop_monitoring(self):
        """停止监控"""
        self.monitoring_active = False
        if self.monitoring_thread:
            self.monitoring_thread.join(timeout=5)
        print("存储监控已停止")
    
    def _monitoring_loop(self, interval: int):
        """监控循环"""
        while self.monitoring_active:
            try:
                # 调整存储策略
                result = self.adjust_storage_strategy()
                
                if result['adjusted']:
                    print(f"存储策略已调整: {result['new_config']}")
                
                # 等待下次检查
                time.sleep(interval)
                
            except Exception as e:
                print(f"监控循环错误: {e}")
                time.sleep(interval)
    
    def get_storage_status(self) -> Dict[str, Any]:
        """获取存储状态"""
        disk_info = self.disk_monitor.get_disk_info()
        recommendation = self.disk_monitor.get_storage_recommendation(disk_info)
        db_size = self.disk_monitor.get_database_size()
        memory_info = self.disk_monitor.get_memory_usage()
        
        return {
            'disk_info': {
                'total': disk_info.total,
                'used': disk_info.used,
                'free': disk_info.free,
                'percentage': disk_info.percentage,
                'level': disk_info.level.value
            },
            'database_size': db_size,
            'memory_info': memory_info,
            'current_config': {
                'buffer_size': self.current_config.buffer_size,
                'max_pages': self.current_config.max_pages,
                'cleanup_threshold': self.current_config.cleanup_threshold,
                'compression_enabled': self.current_config.compression_enabled,
                'auto_cleanup': self.current_config.auto_cleanup
            },
            'recommendation': {
                'level': recommendation.level.value,
                'message': recommendation.message,
                'actions': recommendation.actions,
                'buffer_size_factor': recommendation.buffer_size_factor,
                'page_cleanup_threshold': recommendation.page_cleanup_threshold
            },
            'monitoring_active': self.monitoring_active,
            'last_adjustment_time': self.last_adjustment_time
        }
    
    def print_status(self):
        """打印存储状态"""
        status = self.get_storage_status()
        
        print("=" * 60)
        print("存储策略状态")
        print("=" * 60)
        print(f"监控状态: {'活跃' if status['monitoring_active'] else '停止'}")
        print(f"最后调整时间: {time.ctime(status['last_adjustment_time'])}")
        print()
        
        # 磁盘信息
        disk_info = status['disk_info']
        print("磁盘信息:")
        print(f"  总空间: {self.disk_monitor.format_size(disk_info['total'])}")
        print(f"  已使用: {self.disk_monitor.format_size(disk_info['used'])} ({disk_info['percentage']:.1f}%)")
        print(f"  可用空间: {self.disk_monitor.format_size(disk_info['free'])}")
        print(f"  存储级别: {disk_info['level']}")
        print()
        
        # 数据库信息
        print("数据库信息:")
        print(f"  数据库大小: {self.disk_monitor.format_size(status['database_size'])}")
        print()
        
        # 当前配置
        config = status['current_config']
        print("当前配置:")
        print(f"  缓冲区大小: {config['buffer_size']}")
        print(f"  最大页面数: {config['max_pages']}")
        print(f"  清理阈值: {config['cleanup_threshold']}")
        print(f"  压缩启用: {'是' if config['compression_enabled'] else '否'}")
        print(f"  自动清理: {'是' if config['auto_cleanup'] else '否'}")
        print()
        
        # 建议
        recommendation = status['recommendation']
        print("存储建议:")
        print(f"  级别: {recommendation['level']}")
        print(f"  消息: {recommendation['message']}")
        print(f"  缓冲区调整因子: {recommendation['buffer_size_factor']}")
        print(f"  页面清理阈值: {recommendation['page_cleanup_threshold']}")
        print("  建议操作:")
        for action in recommendation['actions']:
            print(f"    - {action}")
    
    def force_cleanup(self) -> Dict[str, Any]:
        """强制清理"""
        print("执行强制清理...")
        
        # 清理临时文件
        cleaned_files = self.disk_monitor.cleanup_temp_files()
        
        # 获取清理后的磁盘信息
        disk_info = self.disk_monitor.get_disk_info()
        
        # 触发清理事件
        self._trigger_callback('force_cleanup', {
            'cleaned_files': cleaned_files,
            'disk_info': disk_info
        })
        
        return {
            'cleaned_files': cleaned_files,
            'disk_info': disk_info
        }
    
    def set_adjustment_cooldown(self, seconds: int):
        """设置调整冷却时间"""
        self.adjustment_cooldown = max(10, seconds)  # 最少10秒
        print(f"调整冷却时间设置为: {self.adjustment_cooldown}秒")